using System;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
using Vision.Abstractions;

namespace Vision.Devices
{
	/// <summary>
	/// 模拟相机：定时生成灰度测试图像并写入图像总线。
	/// </summary>
	public class FakeCamera : IDevice
	{
		private readonly ChannelWriter<Message> _writer;
		private CancellationTokenSource? _cts;
		private Task? _processTask;
		private long _frameNumber;
		private int _delay=10;

		public bool IsRunning => _processTask != null && !_processTask.IsCompleted;
		
		public int Delay => _delay;


		public FakeCamera(ChannelWriter<Message> writer)
		{
			_writer = writer;
		}

		public Task InitializeAsync()
		{
			return Task.CompletedTask;
		}

		public Task StartAsync(CancellationToken cancellationToken)
		{
			if (IsRunning)
				return Task.CompletedTask;

			_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
			_processTask = ProcessAsync(_cts.Token);
			return Task.CompletedTask;
		}

		public async Task StopAsync(CancellationToken cancellationToken)
		{
			if (_cts != null)
			{
				await _cts.CancelAsync();
				if (_processTask != null)
				{
					try 
					{
                        // 设置超时，避免无限等待
                        using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(2));
                        using var combinedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token);

                        await _processTask.WaitAsync(combinedCts.Token);
                    }
					catch (Exception ex) 
					{
                        //提示错误
                        Console.WriteLine($"Error stopping FakeCamera: {ex.Message}");
                    }
				}
				_cts.Dispose();
				_cts = null;
				_processTask = null;
			}
		}

		/// <summary>
		/// 后台生成假图像并投递到总线。
		/// </summary>
		private async Task ProcessAsync(CancellationToken cancellationToken)
		{
			var width = 640;
			var height = 480;
            long frame = 0;
            while (!cancellationToken.IsCancellationRequested)
			{
                // 每帧向下偏移一行
                var data = GenerateFakeImage(width, height, (int)(frame % height));
                var message = new CameraFrameMessage(data, width, height);
				await _writer.WriteAsync(message, cancellationToken);
				await Task.Delay(this._delay, cancellationToken);
                frame++;
            }
			Console.WriteLine("FakeCamera stopped.");
        }

		public void SetDelay(int delay)
		{
			this._delay = delay;
        }

        /// <summary>
        /// 生成可循环向下移动的灰度渐变图。
        /// </summary>
        private static byte[] GenerateFakeImage(int width, int height, int yOffset)
        {
            var data = new byte[width * height];
            for (int y = 0; y < height; y++)
            {
                int yMoved = (y + yOffset) % height;
                for (int x = 0; x < width; x++)
                {
                    data[y * width + x] = (byte)((x + yMoved) % 256);
                }
            }
            return data;
        }

        public void Dispose()
		{
			_cts?.Dispose();
			GC.SuppressFinalize(this);
		}
	}
}


